x86/EFI: pass boot services variable info to runtime code
authorJan Beulich <jbeulich@suse.com>
Mon, 22 Apr 2013 11:58:01 +0000 (13:58 +0200)
committerJan Beulich <jbeulich@suse.com>
Mon, 22 Apr 2013 11:58:01 +0000 (13:58 +0200)
EFI variables can be flagged as being accessible only within boot services.
This makes it awkward for us to figure out how much space they use at
runtime. In theory we could figure this out by simply comparing the results
from QueryVariableInfo() to the space used by all of our variables, but
that fails if the platform doesn't garbage collect on every boot. Thankfully,
calling QueryVariableInfo() while still inside boot services gives a more
reliable answer. This patch passes that information from the EFI boot stub
up to the efi platform code.

Based on a similarly named Linux patch by Matthew Garrett <matthew.garrett@nebula.com>.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Keir Fraser <keir@xen.org>
Acked-by: George Dunlap <george.dunlap@eu.citrix.com>
xen/arch/x86/efi/boot.c
xen/arch/x86/efi/efi.h
xen/arch/x86/efi/runtime.c
xen/include/efi/efiapi.h
xen/include/public/platform.h

index 3de0ce7e544401702d45c431f2efc9287017c753..44bc7b7670696204f57a217604f1e4503d9418fc 100644 (file)
@@ -1240,6 +1240,23 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     /* Collect PCI ROM contents. */
     setup_efi_pci();
 
+    /* Get snapshot of variable store parameters. */
+    status = efi_rs->QueryVariableInfo(EFI_VARIABLE_NON_VOLATILE |
+                                       EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                                       EFI_VARIABLE_RUNTIME_ACCESS,
+                                       &efi_boot_max_var_store_size,
+                                       &efi_boot_remain_var_store_size,
+                                       &efi_boot_max_var_size);
+    if ( EFI_ERROR(status) )
+    {
+        efi_boot_max_var_store_size = 0;
+        efi_boot_remain_var_store_size = 0;
+        efi_boot_max_var_size = status;
+        PrintStr(L"Warning: Could not query variable store: ");
+        DisplayUint(status, 0);
+        PrintStr(newline);
+    }
+
     /* Allocate space for trampoline (in first Mb). */
     cfg.addr = 0x100000;
     cfg.size = trampoline_end - trampoline_start;
index 43dbd1728bc50419ed10fac89491a656ce3412f0..a80d5f1abb0e5c71351a3d3f49557dab88b5cbb9 100644 (file)
@@ -32,5 +32,8 @@ extern l4_pgentry_t *efi_l4_pgtable;
 
 extern const struct efi_pci_rom *efi_pci_roms;
 
+extern UINT64 efi_boot_max_var_store_size, efi_boot_remain_var_store_size,
+              efi_boot_max_var_size;
+
 unsigned long efi_rs_enter(void);
 void efi_rs_leave(unsigned long);
index aafdfebdd848b1ee6af9e980bd3c151133374c06..be3f5376b3a61e4fd32bf5b8dc9f652f86b4ee57 100644 (file)
@@ -28,6 +28,10 @@ UINTN __read_mostly efi_memmap_size;
 UINTN __read_mostly efi_mdesc_size;
 void *__read_mostly efi_memmap;
 
+UINT64 __read_mostly efi_boot_max_var_store_size;
+UINT64 __read_mostly efi_boot_remain_var_store_size;
+UINT64 __read_mostly efi_boot_max_var_size;
+
 struct efi __read_mostly efi = {
        .acpi   = EFI_INVALID_TABLE_ADDR,
        .acpi20 = EFI_INVALID_TABLE_ADDR,
@@ -464,6 +468,35 @@ int efi_runtime_call(struct xenpf_efi_runtime_call *op)
     break;
 
     case XEN_EFI_query_variable_info:
+        if ( op->misc & ~XEN_EFI_VARINFO_BOOT_SNAPSHOT )
+            return -EINVAL;
+
+        if ( op->misc & XEN_EFI_VARINFO_BOOT_SNAPSHOT )
+        {
+            if ( (op->u.query_variable_info.attr
+                  & ~EFI_VARIABLE_APPEND_WRITE) !=
+                 (EFI_VARIABLE_NON_VOLATILE |
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                  EFI_VARIABLE_RUNTIME_ACCESS) )
+                return -EINVAL;
+
+            op->u.query_variable_info.max_store_size =
+                efi_boot_max_var_store_size;
+            op->u.query_variable_info.remain_store_size =
+                efi_boot_remain_var_store_size;
+            if ( efi_boot_max_var_store_size )
+            {
+                op->u.query_variable_info.max_size = efi_boot_max_var_size;
+                status = EFI_SUCCESS;
+            }
+            else
+            {
+                op->u.query_variable_info.max_size = 0;
+                status = efi_boot_max_var_size;
+            }
+            break;
+        }
+
         cr3 = efi_rs_enter();
         if ( (efi_rs->Hdr.Revision >> 16) < 2 )
         {
@@ -480,6 +513,9 @@ int efi_runtime_call(struct xenpf_efi_runtime_call *op)
 
     case XEN_EFI_query_capsule_capabilities:
     case XEN_EFI_update_capsule:
+        if ( op->misc )
+            return -EINVAL;
+
         cr3 = efi_rs_enter();
         if ( (efi_rs->Hdr.Revision >> 16) < 2 )
         {
index 7c276cfc63597d0569333954c316afa8bce73ed3..a616d1238aa44abf59195fc8b49c6c47e5af8aa9 100644 (file)
@@ -213,6 +213,10 @@ VOID
 #define EFI_VARIABLE_NON_VOLATILE           0x00000001
 #define EFI_VARIABLE_BOOTSERVICE_ACCESS     0x00000002
 #define EFI_VARIABLE_RUNTIME_ACCESS         0x00000004
+#define EFI_VARIABLE_HARDWARE_ERROR_RECORD  0x00000008
+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010
+#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020
+#define EFI_VARIABLE_APPEND_WRITE           0x00000040
 
 // Variable size limitation
 #define EFI_MAXIMUM_VARIABLE_SIZE           1024
index d7d2a5bddffb79ae8ac11d4ffbe5e4795f76fd59..4341f5462c0987872e725ed00b5f231ac4b173b6 100644 (file)
@@ -184,6 +184,7 @@ struct xenpf_efi_runtime_call {
             struct xenpf_efi_guid vendor_guid;
         } get_next_variable_name;
 
+#define XEN_EFI_VARINFO_BOOT_SNAPSHOT       0x00000001
         struct {
             uint32_t attr;
             uint64_t max_store_size;